#include "semi/logg/Logger.h"
#include "semi/SessionContext.h"
#include "semi/SharedRecord.h"
// #include "semi/InitialEvent.h"

using namespace std;
using namespace semi;
using namespace semi::conf;
using namespace semi::logg;

struct TEST_ST {
    char user[64];
    char pass[64];
    char url[64];
    char urn[64];
}; // 256

void testEnd() {

    posix::SharedMemory mem1("TEST_ST1", sizeof(TEST_ST));
    TEST_ST* st1 = (TEST_ST*) mem1.get();
    memset(st1, 0, sizeof(TEST_ST));
    strncpy(st1->user, "TEST_USR1", 9);
    mem1.end();

    posix::SharedMemory mem2("TEST_ST1", sizeof(TEST_ST));
    TEST_ST* st2 = (TEST_ST*) mem2.get();
    mem2.end();
    cout << "after end " << st2->user << endl;
    strncpy(st2->user, "TEST_USR2", 9);
    //    mem2.end();
    st2 = (TEST_ST*) mem2.get();
    cout << "after end setted " << st2->user << endl;

    //    mem2.unmap();
    //    cout << "after unmap " << st2->user << endl;
    //    strncpy(st2->user, "TEST_USR3", 9);
    //    //    mem2.end();
    //    st2 = (TEST_ST*) mem2.get();
    //    cout << "after unmap setted " << st2->user << endl;
    //    strncpy(st1->user, "TEST_USR3", 8);

    //    posix::SharedMemory mem3("TEST_ST1", sizeof(TEST_ST));
    //    TEST_ST* st3 = (TEST_ST*) mem3.get();
    //    mem3.end();
    //    cout << "after unmap " << st3->user << endl;
}

void testContextList() {

    SharedContext c1("TEST_ST1", sizeof(TEST_ST));
    SharedContext c2("TEST_ST1", sizeof(TEST_ST));
    SessionContext c3("TEST_ST2", sizeof(TEST_ST));
    SessionContext c4("TEST_ST3", sizeof(TEST_ST));

}

//void testTerminate() {
//
//    SharedContext mem1("TEST_ST1", sizeof(TEST_ST));
//    TEST_ST* st1 = (TEST_ST*) mem1.get();
//
//    SessionContext mem2("TEST_ST2", sizeof(TEST_ST));
//    TEST_ST* st2 = (TEST_ST*) mem2.get();
//
//    SessionContext::terminateAll();
//
//}
//
//void testLock() {
//
//    SharedContext mem1("TEST_ST1", sizeof(TEST_ST), true);
//    TEST_ST * st1 = (TEST_ST*) mem1.get();
//    // mem1.end();
//    cout << "testLock1 get ok" << endl;
//
//    SharedContext mem2("TEST_ST1", sizeof(TEST_ST), true);
//    TEST_ST * st2 = (TEST_ST*) mem2.get();
//    cout << "testLock1 end" << endl;
//}

//void testLock2() {
//
//    SharedContext mem1("TEST_ST1", sizeof(TEST_ST), true);
//    // SharedContext mem1("TEST_ST2", sizeof(TEST_ST), true);
//    // mem1.releaseLock();
//    TEST_ST* st1 = (TEST_ST*) mem1.get();
//    cout << "testLock2 get ok" << endl;
//
//    sleep(5);
//
//    mem1.end();
//    cout << "testLock2 end" << endl;
//}

void testSet() {

    //    SharedContext sharedContext0("TEST_ST1", sizeof(TEST_ST));
    //    TEST_ST* st0 = (TEST_ST*) sharedContext0.get();
    //    cout << "after get st0 " << st0->user << endl;
    //    sharedContext0.end();
    //
    //    SharedContext sharedContext1("TEST_ST1", sizeof(TEST_ST));
    //    strncpy(st0->user, "TEST_USR1", 9);
    //    sharedContext1.set((void*) st0);
    //    std::cout << "set st0 " << std::string((char*) st0) << " " << st0
    //            << std::endl;
    //    sharedContext1.end();

    SharedContext sharedContext1("TEST_ST1", sizeof(TEST_ST));
    TEST_ST st1;
    memset(&st1, 0, sizeof(TEST_ST));
    strncpy(&(st1.user[0]), "TEST_USR4", 9);
    sharedContext1.set(&st1);
    cout << "after set st1 " << st1.user << endl;
    sharedContext1.end();

    SharedContext sharedContext2("TEST_ST1", sizeof(TEST_ST));
    //    TEST_ST* st2 = (TEST_ST*) sharedContext2.get();
    TEST_ST st2;
    memset(&st2, 0, sizeof(TEST_ST)); // 256
    sharedContext2.get(&st2);
    cout << "after get st2 " << st2.user << endl;
    sharedContext2.end();
    cout << "after end st2 " << st2.user << endl;

    //    SessionContext mem2("TEST_ST2", sizeof(TEST_ST));
    //    TEST_ST* st2 = (TEST_ST*) mem2.get();


}

void testSes() {

    //    SessionContext ctx1("TEST_ST_SES", sizeof(TEST_ST));
    //    TEST_ST st1;
    //    memset(&st1, 0, sizeof(TEST_ST)); // 256
    //    strncpy(&(st1.user[0]), "SESTEST_USR1", 12);
    //    ctx1.set(&st1);
    //    cout << "testSes set " << st1.user << endl;
    //    ctx1.end();

    SessionContext ctx1("TEST_ST_SES", sizeof(TEST_ST));
    TEST_ST st1;
    memset(&st1, 0, sizeof(TEST_ST)); // 256
    strncpy(&(st1.user[0]), "SESTEST_USR1", 12);
    ctx1.set(&st1);
    cout << "testSes set " << st1.user << endl;
    ctx1.end();

    SessionContext ctx2("TEST_ST_SES", sizeof(TEST_ST));
    //    TEST_ST* st2 = (TEST_ST*) ctx2.get();
    TEST_ST st2;
    memset(&st2, 0, sizeof(TEST_ST)); // 256
    ctx2.get(&st2);
    cout << "testSes get " << st2.user << endl;
    ctx2.end();
}

void testRec() {

    TEST_ST st1;
    memset(&st1, 0, sizeof(TEST_ST)); // 256
    strncpy(&st1.user[0], "TEST_RECUSR", 11);

    SharedRecord ctx1("TEST_ST_REC", sizeof(TEST_ST), 10, true);

    cout << "testRec set " << st1.user << endl;
    ctx1.set((void*) &st1, 2, 1);
    std::cout << "set st1 " << std::string((char*) &st1) << " " << (int) &st1
            << std::endl;
    ctx1.end();
    cout << "testRec set " << st1.user << endl;

    SharedRecord ctx2("TEST_ST_REC", sizeof(TEST_ST), 10, true);
    //    TEST_ST* st2 = (TEST_ST*) ctx2.get(2, 1);
    TEST_ST st2;
    memset(&st2, 0, sizeof(TEST_ST)); // 256
    ctx2.get(&st2, 2, 1);
    cout << "testRec get " << st2.user << " " << &st2 << endl;
    ctx2.end();
    std::cout << "get st2 " << std::string((char*) &st2) << " " << (int) &st2
            << std::endl;
}

int main() {

    // SharedContext::releaseAllLocks();
    // semi::logg::Logger::terminateAll();

    // std::cout << SharedContext::toString() << std::endl;

    //    testEnd();
    //    testContextList();
    //    testTerminate();

    // testLock();

    testSet();
    // testSes();
    //    testRec();

    std::cout << SharedContext::toString() << std::endl;

    return 0;
}
